#ifndef ERROR_H
#define ERROR_H

#ifdef __cplusplus
extern "C" {
#endif

// Keep in sync with the lists error_message and error_type
typedef enum {
    /* Shared errors */
    //ERROR_SUCCESS = 0,
    ERROR_FAILURE = ERROR_SUCCESS + 1,
    ERROR_INTERNAL,

    /* VFS user errors */
    ERROR_ERROR_DURING_TRANSFER,
    ERROR_TRANSFER_TIMEOUT,
    ERROR_FILE_BOUNDS,
    ERROR_OOO_SECTOR,

    /* Target flash errors */
    ERROR_RESET,
    ERROR_ALGO_DL,
    ERROR_ALGO_DATA_SEQ,
    ERROR_INIT,
    ERROR_SECURITY_BITS,
    ERROR_UNLOCK,
    ERROR_ERASE_SECTOR,
    ERROR_ERASE_ALL,
    ERROR_WRITE,

    /* File stream errors */
    ERROR_SUCCESS_DONE,
    ERROR_SUCCESS_DONE_OR_CONTINUE,
    ERROR_HEX_CKSUM,
    ERROR_HEX_PARSER,
    ERROR_HEX_PROGRAM,
    ERROR_HEX_INVALID_ADDRESS,
    ERROR_HEX_INVALID_APP_OFFSET,

    /* Flash decoder error */
    ERROR_FD_BL_UPDT_ADDR_WRONG,
    ERROR_FD_INTF_UPDT_ADDR_WRONG,
    ERROR_FD_UNSUPPORTED_UPDATE,

    /* Flash IAP interface */
    ERROR_IAP_INIT,
    ERROR_IAP_UNINIT,
    ERROR_IAP_WRITE,
    ERROR_IAP_ERASE_SECTOR,
    ERROR_IAP_ERASE_ALL,
    ERROR_IAP_OUT_OF_BOUNDS,
    ERROR_IAP_UPDT_NOT_SUPPORTED,
    ERROR_IAP_UPDT_INCOMPLETE,
    ERROR_IAP_NO_INTERCEPT,
    ERROR_BL_UPDT_BAD_CRC,

    // Add new values here
    ERROR_IAP_ERASE_PAGE,
    ERROR_IAP_READ,
    ERROR_IAP_RUN_APP,
    ERROR_IAP_WRITE_OPTION_BYTES,

    ERROR_USB_GET_DEVICE_LIST,
    ERROR_USB_OPEN,

    ERROR_COM_OPEN,

    ERROR_ISP_0x7F,
    ERROR_ISP_Get,
    ERROR_ISP_GetVersionAndReadProtectionStatus,
    ERROR_ISP_GetID,
    ERROR_ISP_WriteProtect,
    ERROR_ISP_WriteUnprotect,
    ERROR_ISP_ReadoutProtect,
    ERROR_ISP_ReadoutUnprotect,

    ERROR_GET_UID,
    ERROR_GET_FLASH_SRAM_SIZE,
    ERROR_VERIFY_OPTION_BYTES,

    ERROR_COUNT
} error_t;

const CString error_message[] = {

    /* Shared errors */

    // ERROR_SUCCESS
    _T("Operation was successful"),
    // ERROR_FAILURE
    _T("An error has occurred"),
    // ERROR_INTERNAL
    _T("An internal error has occurred"),

    /* VFS user errors */

    // ERROR_ERROR_DURING_TRANSFER
    _T("An error occurred during the transfer"),
    // ERROR_TRANSFER_TIMEOUT
    _T("The transfer timed out."),
    // ERROR_FILE_BOUNDS
    _T("Possible mismatch between file size and size programmed"),
    // ERROR_OOO_SECTOR
    _T("File sent out of order by PC. Target might not be programmed correctly."),

    /* Target flash errors */

    // ERROR_RESET
    _T("The interface firmware FAILED to reset/halt the target MCU"),
    // ERROR_ALGO_DL
    _T("The interface firmware FAILED to download the flash programming algorithms to the target MCU"),
    // ERROR_ALGO_DATA_SEQ
    _T("The interface firmware FAILED to download the flash data contents to be programmed"),
    // ERROR_INIT
    _T("The interface firmware FAILED to initialize the target MCU"),
    // ERROR_SECURITY_BITS
    _T("The interface firmware ABORTED programming. Image is trying to set security bits"),
    // ERROR_UNLOCK
    _T("The interface firmware FAILED to unlock the target for programming"),
    // ERROR_ERASE_SECTOR
    _T("Flash algorithm erase sector command FAILURE"),
    // ERROR_ERASE_ALL
    _T("Flash algorithm erase all command FAILURE"),
    // ERROR_WRITE
    _T("Flash algorithm write command FAILURE"),

    /* File stream errors */

    // ERROR_SUCCESS_DONE
    _T("End of stream has been reached"),
    // ERROR_SUCCESS_DONE_OR_CONTINUE
    _T("End of stream is unknown"),
    // ERROR_HEX_CKSUM
    _T("The hex file cannot be decoded. Checksum calculation failure occurred."),
    // ERROR_HEX_PARSER
    _T("The hex file cannot be decoded. Parser logic failure occurred."),
    // ERROR_HEX_PROGRAM
    _T("The hex file cannot be programmed. Logic failure occurred."),
    // ERROR_HEX_INVALID_ADDRESS
    _T("The hex file you dropped isn't compatible with this mode or device. Are you in MAINTENANCE mode? See HELP FAQ.HTM"),
    // ERROR_HEX_INVALID_APP_OFFSET
    _T("The hex file offset load address is not correct."),

    /* Flash decoder errors */

    // ERROR_FD_BL_UPDT_ADDR_WRONG
    _T("The starting address for the bootloader update is wrong."),
    // ERROR_FD_INTF_UPDT_ADDR_WRONG
    _T("The starting address for the interface update is wrong."),
    // ERROR_FD_UNSUPPORTED_UPDATE
    _T("The application file format is unknown and cannot be parsed and/or processed."),

    /* Flash IAP interface */

    // ERROR_IAP_INIT
    _T("In application programming initialization failed."),
    // ERROR_IAP_UNINIT
    _T("In application programming uninit failed."),
    // ERROR_IAP_WRITE
    _T("In application programming write failed."),
    // ERROR_IAP_ERASE_SECTOR
    _T("In application programming sector erase failed."),
    // ERROR_IAP_ERASE_ALL
    _T("In application programming mass erase failed."),
    // ERROR_IAP_OUT_OF_BOUNDS
    _T("In application programming aborted due to an out of bounds address."),
    // ERROR_IAP_UPDT_NOT_SUPPORTED
    _T("In application programming not supported on this device."),
    // ERROR_IAP_UPDT_INCOMPLETE
    _T("In application programming failed because the update sent was incomplete."),
    // ERROR_IAP_NO_INTERCEPT
    _T(""),
    // ERROR_BL_UPDT_BAD_CRC
    _T("The bootloader CRC did not pass."),

    // Add new values here

    //ERROR_IAP_ERASE_PAGE
    _T("In application programming page erase failed."),
    //ERROR_IAP_READ
    _T("In application programming read failed."),
    //ERROR_IAP_RUN_APP
    _T("In application programming run application failed."),
    //ERROR_IAP_WRITE_OPTION_BYTES
    _T("In application programming write option bytes failed."),

    //ERROR_USB_GET_DEVICE_LIST
    _T("Get USB device list failed."),
    //ERROR_USB_OPEN
    _T("Open USB failed."),

    //ERROR_COM_OPEN
    _T("Open COM failed."),

    //ERROR_ISP_0x7F
    _T("In system programming process 0x7F command failed."),
    //ERROR_ISP_Get
    _T("In system programming process Get command failed."),
    //ERROR_ISP_GetVersionAndReadProtectionStatus
    _T("In system programming process GetVersionAndReadProtectionStatus command failed."),
    //ERROR_ISP_GetID
    _T("In system programming process GetID command failed."),
    //ERROR_ISP_WriteProtect
    _T("In system programming process WriteProtect command failed."),
    //ERROR_ISP_WriteUnprotect
    _T("In system programming process WriteUnprotect command failed."),
    //ERROR_ISP_ReadoutProtect
    _T("In system programming process ReadoutProtect command failed."),
    //ERROR_ISP_ReadoutUnprotect
    _T("In system programming process ReadoutUnprotect command failed."),

    //ERROR_GET_UID
    _T("Get UID failed."),
    //ERROR_GET_FLASH_SRAM_SIZE
    _T("Get FLASH/SRAM size failed."),
    //ERROR_GET_OPTION_BYTES
    _T("Verify option bytes failed."),
};

#define ERROR_TYPE_INTERNAL 0x1
#define ERROR_TYPE_TRANSIENT 0x2
#define ERROR_TYPE_USER 0x4
#define ERROR_TYPE_TARGET 0x8
#define ERROR_TYPE_INTERFACE 0x10
    // If you add another error type:
    // 1. update error_type_names, used by read_file_fail_txt()
    // 2. update ERROR_TYPE_MASK
    // 3. make sure that error type bits still fit inside of error_type_t
#define ERROR_TYPE_MASK 0x1F

#ifdef __cplusplus
}
#endif

#endif
